package Engines;

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.net.*;

import MyGui.*;
import DistSys.*;
import Element.*;
import Element.Geom.*;

public class EngineThread extends Thread {
  public static final int ENG_QUICKFLOW = 0;
  public static final int ENG_NETFLOW   = 1;
  public static final int ENG_DISTREL   = 2;
  public static final int ENG_NETREL    = 3;
  public static final int ENG_SENS_RAD  = 4;
  public static final int ENG_SENS_NET  = 5;
  public static final int ENG_RISK_RAD  = 6;
  public static final int ENG_RISK_NET  = 7;
  public static final int ENG_SHTCKT    = 8;
  public static final int ENG_SECURITY  = 9;

  public  boolean stopNow;
  private MainFrame mainFrame;
  private SensitivityDlg sensDlg; //from which this thread is created;
  private RiskAnalysisDlg   riskDlg;
  private int analysisID;
  private String strURL;
  private String finalMsg;

  public EngineThread( MainFrame f,  String s,  int analysis) {
      this.mainFrame=f;
      this.strURL = s;
      this.analysisID =analysis;
      this.stopNow = false;
  }

  //used by sensitivity analysis
  public EngineThread( MainFrame f, MyDlgFrame dlg, String s, int analysis){
      this.mainFrame=f;
      if( dlg instanceof SensitivityDlg) { this.sensDlg = (SensitivityDlg)dlg; }
      else if( dlg instanceof RiskAnalysisDlg) { this.riskDlg = (RiskAnalysisDlg)dlg; }
      this.strURL = s;
      this.analysisID =analysis;
      this.stopNow = false;
  }

  public void run(){
    try {
      if(strURL == null ){
          stopNow = true;
          return;
      }

      stopNow = false;  //protective redundency
      mainFrame.getContentPane().setCursor(Cursor.getPredefinedCursor(
          Cursor.WAIT_CURSOR));
      switch (analysisID) {
        case ENG_QUICKFLOW:
                  callQuickFlow();
                  SysConst.progress =20;
                  if (!stopNow){
                      //JOptionPane.showMessageDialog(mainFrame, finalMsg);
                  }
                  break;
        case ENG_NETFLOW:
        case ENG_SHTCKT:
        case ENG_SECURITY:
                  callNetFlow();
                  SysConst.progress = 20;
                  if (!stopNow){
                      //JOptionPane.showMessageDialog(mainFrame,
                      //    "Network power flow complete.");
                  }
                  break;
        case ENG_DISTREL:
                  callDistRel();
                  SysConst.progress =20;
                  if (!stopNow){
                      //JOptionPane.showMessageDialog(mainFrame,
                      //    "Reliability assessment complete.");
                  }
                  break;
        case ENG_NETREL:
                  callNetRel();
                  SysConst.progress =20;
                  if (!stopNow) {
                      //JOptionPane.showMessageDialog(mainFrame,
                      //    "Network reliability analysis complete.");
                  }
                  break;
        case ENG_SENS_RAD:
        case ENG_SENS_NET:
                  callSensitivityAnalysis(); //need to call Distrel/Netrel twice
                  SysConst.progress =20;
                  sensDlg.completed(stopNow);
                  break;
        case ENG_RISK_RAD:
                  callDistRel();
                  SysConst.progress =20;
                  if (!stopNow) {
                      //JOptionPane.showMessageDialog(mainFrame,
                      //    "Risk analysis complete.");
                  }
                  break;

        default:  JOptionPane.showMessageDialog(mainFrame,"Error Mode.");
                  break;
      }
    } catch (Exception e) {
        e.printStackTrace();
        JOptionPane.showMessageDialog(mainFrame,
            "Exception occured during running enignes!!!\n" +
            "Exception="+e.toString() );
    } finally {
        SysConst.progress =20;
        mainFrame.getMainMenuBar().setCurrentShadingOption(Sys.prjInfo.shadingCat);
        mainFrame.getMainPanel().setNeedRedraw(true);
        mainFrame.getMainPanel().repaint();
        mainFrame.getContentPane().setCursor(Cursor.getPredefinedCursor(
              Cursor.DEFAULT_CURSOR));
        stopNow = true;
    }
  }

  private void callSensitivityAnalysis() throws Exception{
    SysConst.progress=0;
    if( analysisID == ENG_SENS_RAD ) { callDistRel(); }
    else { callNetRel(); }
    sensDlg.calcIndicesForBaseCase();

    SysConst.progress=0;
    sensDlg.perturbZone();
    if( analysisID == ENG_SENS_RAD ) { callDistRel(); }
    else { callNetRel(); }
    sensDlg.calcIndicesForPerturbedCase();

    //compute sensitivity
    sensDlg.computeAndUpdateSensitivity();

    //restore values
    sensDlg.restorePara();
  }

  private void callQuickFlow() throws Exception{
    SysConst.progress = 0;
    Sys.buildSystemTopo();
    if( Sys.isRadial == false) {
      JOptionPane.showMessageDialog(mainFrame,
          "Please check Topology to make sure the system is radial!");
      return;
    }

    deleteFilesForQuickFlow();
    EngineProcessor.writeQuickFlowOut();

    // open a web page containing the ActiveX Distrel Engine
    mainFrame.showDocument(strURL, "TOP");

    File statusFile = new File(Sys.personalInfo.getTempPath(),
                               EngineProcessor.QUICKFLOW_STATUS);
    waitForEngine(statusFile);
    if (stopNow == true) { return; }

    SysConst.progressMsg = "Reading results...";
    EngineProcessor.readQuickFlowIn();  // READ THE DATA IN !!!
    if (SysConst.DEBUG_MODE == 0)
      deleteFilesForQuickFlow();
    //SysConst.progress = 20;
  }// end of callQuickFlow()

  private void callNetFlow( ) throws Exception {
    SysConst.progress=0;

    deleteFilesForNetFlow();
    EngineProcessor.writeNetFlowOut();

    // open a web page containing the ActiveX Distrel Engine
    mainFrame.showDocument(strURL, "TOP");

    File statusFile = new File(Sys.personalInfo.getTempPath(),
                               EngineProcessor.NETFLOW_STATUS);
    waitForEngine(statusFile);
    if (stopNow == true) { return; }

    SysConst.progressMsg="Reading results...";
    if      ( analysisID == ENG_NETFLOW ) { EngineProcessor.readNetFlowIn(); }
    else if ( analysisID == ENG_SHTCKT  ) { EngineProcessor.readShortCircuitIn(); }
    else if ( analysisID == ENG_SECURITY) { EngineProcessor.readSecurityIn(); }

    if (SysConst.DEBUG_MODE == 0) { deleteFilesForNetFlow(); }
  }//end of callNetFlow()

  private void callDistRel() throws Exception{
    SysConst.progress=0;
    Sys.buildSystemTopo();
    if( Sys.isRadial == false) {
        JOptionPane.showMessageDialog(mainFrame,
            "Please check Topology to make sure the system is radial!");
        return;
    }

    deleteFilesForDistrel();
    EngineProcessor.writeDistRelOut();

    // open a web page containing the ActiveX Distrel Engine
    mainFrame.showDocument(strURL, "TOP");

    File statusFile = new File(Sys.personalInfo.getTempPath(),
                               EngineProcessor.DISTREL_STATUS);
    waitForEngine(statusFile);
    if (stopNow == true) { return; }

    SysConst.progressMsg = "Reading results...";
    if (analysisID == ENG_DISTREL || analysisID == ENG_SENS_RAD) {
        EngineProcessor.readDistRelIn();
    } else if (analysisID == ENG_RISK_RAD) {
        riskDlg.engineResults = EngineProcessor.readRiskResults();
        riskDlg.updateGraph();
    }

    if (SysConst.DEBUG_MODE == 0) { deleteFilesForDistrel(); }
    //SysConst.progress =20;
  }//end of callDistrel();

  private void callNetRel() throws Exception{
    SysConst.progress=0;

    deleteFilesForNetrel();
    EngineProcessor.writeNetRelOut();

    // open a web page containing the ActiveX Distrel Engine
    mainFrame.showDocument(strURL, "TOP");

    File statusFile = new File(Sys.personalInfo.getTempPath(),
                               EngineProcessor.NETREL_STATUS);
    waitForEngine(statusFile);
    if (stopNow == true) { return; }

    SysConst.progressMsg="Reading results...";
    EngineProcessor.readNetRelIn();
    if (SysConst.DEBUG_MODE == 0) { deleteFilesForNetrel(); }
  }//end of callDistrel();

  private void deleteFilesForQuickFlow(){
    File f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.QUICKFLOW_DEBUG);
    if (f.exists()) { f.delete(); }
    f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.QUICKFLOW_OUT);
    if (f.exists()) { f.delete(); }
    f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.QUICKFLOW_IN);
    if (f.exists()) { f.delete(); }
    f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.QUICKFLOW_STATUS);
    if (f.exists()) { f.delete(); }
  }

  private void deleteFilesForDistrel() throws Exception{
    File f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.DISTREL_DEBUG);
    if (f.exists()) { f.delete(); }
    f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.DISTREL_OUT);
    if (f.exists()) { f.delete(); }
    f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.DISTREL_IN);
    if (f.exists()) { f.delete(); }
    f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.DISTREL_STATUS);
    if (f.exists()) { f.delete(); }
    f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.RISKRESULTS);
    if (f.exists()) { f.delete(); }
  }

  private void deleteFilesForNetFlow() throws Exception{
    File f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.NETFLOW_DEBUG);
    if (f.exists()) { f.delete(); }
    f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.NETFLOW_OUT);
    if (f.exists()) { f.delete(); }
    f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.NETFLOW_IN);
    if (f.exists()) { f.delete(); }
    f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.NETFLOW_STATUS);
    if (f.exists()) { f.delete(); }
  }

  private void deleteFilesForNetrel() throws Exception{
    File f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.NETREL_DEBUG);
    if (f.exists()) { f.delete(); }
    f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.NETREL_OUT);
    if (f.exists()) { f.delete(); }
    f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.NETREL_IN);
    if (f.exists()) { f.delete(); }
    f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.NETREL_STATUS);
    if (f.exists()) { f.delete(); }
    f = new File(Sys.personalInfo.getTempPath(), EngineProcessor.RISKRESULTS);
    if (f.exists()) { f.delete(); }
  }

  private void waitForEngine(File statusFile) throws Exception{
    try {
        while( true ){
          if( statusFile.exists() ) { break;}
          sleep(500);
        }
    } catch (InterruptedException e) {
    }

    BufferedReader br = new BufferedReader(new FileReader(statusFile));
    String s="";
    int percentProgress=0;
    try {
        while( stopNow==false ) {
            br.close();
            br = new BufferedReader(new FileReader(statusFile));

            s = br.readLine();
            SysConst.progressMsg = s;
            try{
                percentProgress = Integer.parseInt(br.readLine()); //max=100
            } catch(NumberFormatException e) {
                percentProgress = 0;
            }

            // max = 1+ 100/5.56 = 1+ 18 = 19
            SysConst.progress = 1+ (int) Math.round(percentProgress/5.56);
            if( percentProgress >= 100 ){  break; }
            sleep(1000); //1 sec
        }
        finalMsg = new String(s);
    } catch(InterruptedException e) {
    } catch(IOException e) {
        JOptionPane.showMessageDialog(mainFrame,
            "Error Occured @ EngineThread.callDistrel()\n Error = "+e);
    } finally {
        br.close();
    }
  }//end of waitForEngine(File statusFile)
}

  //junk code

  /*private String createUrlString(){
      String str;
      int iBlockSag;
      if( EngineProcessor.bDisableSag ) { iBlockSag=1; } else{ iBlockSag=0; }

      int iPowerFlowBlocked=0, iDoubleContingencies=0, iModelReduction=0;
      if( EngineProcessor.bDisableCapFlow ) { iPowerFlowBlocked=1; }
      if( EngineProcessor.bDisable2ndOrder) { iDoubleContingencies=1; }
      if( EngineProcessor.bUseNetReduction) { iModelReduction=1; }


      switch (analysisID) {
          case ID_QUICKFLOW:
              str = WebConst.getQuickflowURL() +
                  "?PadPath=" + Sys.personalInfo.getTempPath().getPath() +
                  "&Mode=1&Zone=0&ID=0&P1=0&Blocksag=1" +
                  "&TargetMAIFI=0&TargetSAIFI=0&TargetSAIDI=0";
              break;

          case ID_DISTREL:
              str = WebConst.getDistrelURL() +
                  "?PadPath=" + Sys.personalInfo.getTempPath().getPath() +
                  "&Mode=1&Zone="+EngineProcessor.zoneToEng+"&ID=0&P1=0"+
                  "&Blocksag=" + iBlockSag+
                  "&TargetMAIFI=0&TargetSAIFI=0&TargetSAIDI=0";
              break;

          case ID_NETREL:
              str = WebConst.getNetrelURL() +
                  "?PadPath=" + Sys.personalInfo.getTempPath().getPath() +
                  "&PowerFlowBlocked=" + iPowerFlowBlocked +
                  "&DoubleContingenciesBlocked=" + iDoubleContingencies +
                  "&Mode=1"+
                  "&Zone="+EngineProcessor.zoneToEng+
                  "&ModelReduction=" + iModelReduction;
              break;

          case ID_SENS_RAD:
              str = WebConst.getDistrelURL() +
                  "?PadPath=" + Sys.personalInfo.getTempPath().getPath() +
                  "&Mode=1&Zone=1&ID=0&P1=0&Blocksag=1" +
                  "&TargetMAIFI=0&TargetSAIFI=0&TargetSAIDI=0";
              break;

          case ID_SENS_NET:
              str = WebConst.getNetrelURL() +
                  "?PadPath=" + Sys.personalInfo.getTempPath().getPath() +
                  "&PowerFlowBlocked=" + iPowerFlowBlocked +
                  "&DoubleContingenciesBlocked=" + iDoubleContingencies +
                  "&Mode=1"+
                  "&Zone=0"+
                  "&ModelReduction=" + iModelReduction;
              break;
          case ID_RISK_RAD:
              str = WebConst.getDistrelURL() +
                  "?PadPath=" + Sys.personalInfo.getTempPath().getPath() +
                  "&Mode=" + mode +
                  "&Zone=" + zoneInCmdString +
                  "&ID=0&P1=" + sample + "&Blocksag=1" +
                  "&TargetMAIFI=" + maifiWeight +
                  "&TargetSAIFI=" + saifiWeight +
                  "&TargetSAIDI=" + saidiWeight;
              break;

          default:
              JOptionPane.showMessageDialog(mainFrame,
                  "Error Occuered @ EngineThread::createUrlString()");
              return null;
      }
      return urlStr;
  }//end of createUrlString( );
  */